寫到現在其實都還沒考量到瀏灠器重新整理的狀況
所以今天就來寫寫儲存機制吧
由於 Cart 目前是用 $items 的 property 來儲存狀態
所以第一件事情,應該要先把 $items 這個屬於往外抽
先命名為 ArrayStore 吧
再重構的過程中,不應該動到 CartTest 的所有測試案例
所以程式碼如下
namespace Recca0120\Cart\Tests;
use Recca0120\Cart\Cart;
use Recca0120\Cart\Item;
use PHPUnit\Framework\TestCase;
class CartTest extends TestCase
{
/** @test */
public function 將商品加入購物車並驗證商品有名稱單價數量()
{
$item = $this->createItem('商品01', 100, 1);
$cart = new Cart();
$cart->put($item);
$this->assertArraySubset([$item], $cart->items());
}
/** @test */
public function 加總()
{
$cart = new Cart();
$cart->put($this->createItem('商品01', 100, 2));
$cart->put($this->createItem('商品02', 200, 1));
$this->assertEquals(400, $cart->total());
}
/** @test */
public function 移除商品()
{
$cart = new Cart();
$cart->put($item1 = $this->createItem('商品01', 100, 2));
$cart->put($item2 = $this->createItem('商品02', 200, 1));
$cart->remove($item1);
$this->assertEquals([$item2], $cart->items());
}
private function createItem($name, $price, $qty)
{
return new Item([
'name' => $name,
'price' => $price,
'quantity' => $qty,
]);
}
}
// src/ArrayStore.php
namespace Recca0120\Cart;
class ArrayStore
{
private $items = [];
public function put($item)
{
array_push($this->items, $item);
return $this;
}
public function remove($item)
{
$this->items = array_values(array_filter($this->items, function ($o) use ($item) {
return $o !== $item;
}));
}
public function items()
{
return $this->items;
}
}
// src/Cart.php
namespace Recca0120\Cart;
class Cart
{
private $items = [];
private $store;
public function __construct(ArrayStore $store = null)
{
$this->store = $store ?: new ArrayStore();
}
public function put($item)
{
$this->store->put($item);
return $this;
}
public function remove($item)
{
$this->store->remove($item);
}
public function items()
{
return $this->store->items();
}
public function total()
{
return array_sum(array_map(function ($item) {
return $item['total'];
}, $this->items()));
}
}
確認沒問題後,明天就可以進行下一步來將 ArrayStore 改造為 SessionStore